package com.dongnao.jack.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.servlet.http.HttpServletRequest;

import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;

public class HttpUtils {

    private static Logger logger = LoggerFactory.getLogger(HttpUtils.class);

    public static boolean useProxy = true;

    /* public static String proxyHost;
    public static int proxyPort;*/

    private static final String CHARSET = "UTF-8";

    public static String get(String url) {
        return get(url, null, null);
    }

    /**
     * https 证书管理
     */
    private class TrustAnyTrustManager implements X509TrustManager {
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}

        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
    }

    public static CloseableHttpClient createHttpsClient(String url)
            throws NoSuchAlgorithmException, KeyManagementException {
        PoolingHttpClientConnectionManager connManager;
        TrustManager[] tm = { new HttpUtils().new TrustAnyTrustManager() };
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, tm, new java.security.SecureRandom());
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);

        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
                .register("http", PlainConnectionSocketFactory.INSTANCE).register("https", sslsf).build();
        connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);

        connManager.setMaxTotal(Integer.MAX_VALUE);
        connManager.setDefaultMaxPerRoute(Integer.MAX_VALUE);

        // 默认30秒时间超时
        RequestConfig defaultRequestConfig = RequestConfig.custom().setConnectTimeout(30000).setSocketTimeout(30000)
                .build();

        HttpClientBuilder builder = HttpClients.custom().setConnectionManager(connManager)
                .setDefaultRequestConfig(defaultRequestConfig).setKeepAliveStrategy(createKeepAliveStrategy());
        if (useProxy) {

            // fillDataToHostAndPort(url);
            HttpHost proxy = new HttpHost(getHostName(url), getPort(url), "http");
            builder.setProxy(proxy);
        }

        CloseableHttpClient httpclient = builder.build();
        return httpclient;
    }

    private static void fillDataToHostAndPort(String url) {

        /*proxyHost = getHostName(url);
        
        proxyPort = getPort(url);*/

    }

    private static int getPort(String url) {

        if (url != null && url.trim().length() > 0) {

            String urlHost = url;
            if (url.contains("://")) {

                urlHost = url.substring(url.indexOf("://") + 3);
            }
            String string = urlHost.substring(0, urlHost.indexOf("/"));
            if (string.contains(":")) {
                return Integer.parseInt(string.split(":")[1]);
            }

        }

        return 80;
    }

    private static String getHostName(String url) {

        if (url != null && url.trim().length() > 0) {

            String urlHost = url;
            if (url.contains("://")) {

                urlHost = url.substring(url.indexOf("://") + 3);
            }
            String string = urlHost.substring(0, urlHost.indexOf("/"));
            if (string.contains(":")) {
                return string.split(":")[0];
            }

        }

        return null;
    }

    public static ConnectionKeepAliveStrategy createKeepAliveStrategy() {
        ConnectionKeepAliveStrategy myStrategy = new ConnectionKeepAliveStrategy() {
            @Override
            public long getKeepAliveDuration(HttpResponse resp, HttpContext ctx) {
                return 5 * 60 * 1000; // 5分钟的连接缓存
            }
        };
        return myStrategy;
    }

    public static String get(String url, Map<String, String> queryParas) {
        logger.info("--rquestwx begin---url=" + url);
        long begin = System.currentTimeMillis();
        String result = get(url, queryParas, null);
        long end = System.currentTimeMillis();
        logger.info("--rquestwx end---url=" + url + " 耗时:" + (end - begin));
        return result;
    }

    /**
     * Send GET request
     */
    public static String get(String url, Map<String, String> queryParas, Map<String, String> headers) {
        // url = url.replace("https://api.weixin.qq.com", "http://128.160.12.151:9080/TopMallProxy/SendMsg/570001");
        CloseableHttpClient httpclient = null;
        try {
            httpclient = createHttpsClient(url);
            String buildUrl = buildUrlWithQueryString(url, queryParas);
            logger.info("requestUrl=" + buildUrl);
            if (queryParas != null) {
                logger.info("queryParas=" + JSONObject.toJSONString(queryParas));
            }
            HttpGet httpget = new HttpGet(buildUrl);
            if (headers != null && !headers.isEmpty()) {
                for (Entry<String, String> entry : headers.entrySet()) {
                    httpget.setHeader(entry.getKey(), entry.getValue());
                }
            }

            CloseableHttpResponse response = httpclient.execute(httpget);
            int statusCode = response.getStatusLine().getStatusCode();
            logger.info("statusCode=" + statusCode);
            return readResponseString(response);
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
        finally {
            if (httpclient != null) {
                try {
                    httpclient.close();
                }
                catch (IOException e) {
                    logger.error("httpclient.close() exception:", e);
                }
            }
        }
    }

    private static String readResponseString(CloseableHttpResponse response) throws IOException {
        String responseContent = null;
        // 获取响应实体
        HttpEntity entity = response.getEntity();
        if (null != entity) {
            responseContent = EntityUtils.toString(entity, CHARSET);
            // Consume response content
            EntityUtils.consume(entity);
            logger.info("responseContent=" + responseContent);
        }
        return responseContent;
    }

    /**
     * Build queryString of the url
     */
    public static String buildUrlWithQueryString(String url, Map<String, String> queryParas) {
        if (queryParas == null || queryParas.isEmpty()) return url;

        StringBuilder sb = new StringBuilder(url);
        boolean isFirst;
        if (url.indexOf("?") == -1) {
            isFirst = true;
            sb.append("?");
        } else {
            isFirst = false;
        }

        for (Entry<String, String> entry : queryParas.entrySet()) {
            if (isFirst) isFirst = false;
            else sb.append("&");

            String key = entry.getKey();
            String value = entry.getValue();
            if (value != null && value.length() > 0) try {
                value = URLEncoder.encode(value, CHARSET);
            }
            catch (UnsupportedEncodingException e) {
                throw new RuntimeException(e);
            }
            sb.append(key).append("=").append(value);
        }
        return sb.toString();
    }

    public static String post(String url, Map<String, String> queryParas, String data) {
        return post(url, queryParas, data, null);
    }

    public static String post(String url, String data, Map<String, String> headers) {
        return post(url, null, data, headers);
    }

    public static String post(String url, String data) {
        return post(url, null, data, null);
    }

    /**
     * Send POST request
     */
    public static String post(String url, Map<String, String> queryParas, String body, Map<String, String> headers) {
        // url = url.replace("https://api.weixin.qq.com", "http://128.160.12.151:9080/TopMallProxy/SendMsg/570001");
        CloseableHttpClient httpclient = null;

        try {
            httpclient = createHttpsClient(url);
            String buildUrl = buildUrlWithQueryString(url, queryParas);
            HttpPost httpPost = new HttpPost(buildUrl);
            if (headers != null && !headers.isEmpty()) {
                for (Entry<String, String> entry : headers.entrySet()) {
                    httpPost.setHeader(entry.getKey(), entry.getValue());
                }
            }

            if (body != null && body.length() > 0) {
                // String mimeType = "application/x-www-form-urlencoded";//普通的html解析
                // HttpEntity entity = new StringEntity(body, ContentType.create(mimeType, CHARSET));
                String mimeType = "application/json";// 返回的是json数据
                StringEntity entity = new StringEntity(body, ContentType.create(mimeType, CHARSET));// 返回的是json数据
                entity.setContentEncoding("UTF-8");// 返回的是json数据
                httpPost.setEntity(entity);
            }
            logger.info("requestUrl=" + buildUrl);
            if (queryParas != null) {
                logger.info("queryParas=" + JSONObject.toJSONString(queryParas));
            }
            if (body != null) {
                logger.info("body=" + body);
            }
            CloseableHttpResponse response = httpclient.execute(httpPost);
            int statusCode = response.getStatusLine().getStatusCode();
            logger.info("statusCode=" + statusCode);
            return readResponseString(response);
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
        finally {
            if (httpclient != null) {
                try {
                    httpclient.close();
                }
                catch (IOException e) {
                    logger.error("httpclient.close() exception:", e);
                }
            }
        }
    }

    public static String readIncommingRequestData(HttpServletRequest request) {
        BufferedReader br = null;
        try {
            StringBuilder result = new StringBuilder();
            br = request.getReader();
            for (String line = null; (line = br.readLine()) != null;) {
                result.append(line).append("\n");
            }

            return result.toString();
        }
        catch (IOException e) {
            throw new RuntimeException(e);
        }
        finally {
            if (br != null) try {
                br.close();
            }
            catch (IOException e) {
                logger.error("httpclient.readIncommingRequestData() exception:", e);
            }
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {

        /*HttpUtils.useProxy = true;
        HttpUtils.proxyHost = "172.20.20.20";
        HttpUtils.proxyPort = 8080;
        for (int i = 0; i < 5000; i++) {
            String result = HttpUtils.get(
                    "https://api.weixin.qq.com/sns/userinfo?openid=oMD8As4drpt-sHDU2NY1HFQsDcL4&lang=zh_CN&access_token=OezXcEiiBSKSxW0eoylIeEyzINRqPKtGyxMQFGuGJMDYYalVZkdRf8RXhSDNSN-T1Fq_JssVLZHraU1FFcWbAO7GjMJ70KrWuzLGHONMZIGVSPheJu8J8guuajMZHyAungLCCA3dELSOTi_iu2TvUQ");
            System.out.println("get result=" + result);
        }*/

        /*proxyHost = "127.0.0.1";
        proxyPort = 8980;*/
        String url = "http://127.0.0.1:8980/mvcsource/read/readOne";
        Map<String, String> map = new HashMap<>();
        map.put("pageNum", "1");
        map.put("pageSize", "10");
        map.put("pages", "1");
        map.put("total", "1");
        map.put("isAudit", "false");
        map.put("custNo", "102209578");
        String post = post(url, map);
        String get = get(url, map);
        System.out.println(post);
        System.out.println(get);

        // String postResult =
        // post("https://api.weixin.qq.com/cgi-bin/groups/create?access_token=ACCESS_TOKEN","{\"group\":{\"name\":\"test\"}}");
        // System.out.println("postResult = " + postResult);
    }

    /**
     * 
     * @Title: post 
     * @Description: 进行post请求 
     * @param url  请求地址 必须是全路径  如：http://127.0.0.1:8980/mvcsource/read/readOne
     * @param map   封装参数 键值对类型
     * @return 
     * @throws 
     * @author
     * @date 2018年4月23日 上午11:16:27
     */
    public static String post(String url, Map<String, String> map) {

        return post(url, map, "");
    }

}
